#ifndef MICROPROCESADOR_H
#define MICROPROCESADOR_H

#include "global.h"
#include "memoria.h"
#include "instruccion.h"
#include "decodificador.h"

const int cantidad_registros = 14;
const int cantidad_tipos_de_instruccion = 59;
const int tamanio_memoria = 65536; // creo que no sirve para nada


class Microprocesador{
	public:
		Microprocesador(Memoria &mem);
		~Microprocesador();

		void ejecutar();


		//Modificadores
		void setRegistro(Registro registro, byte dato);
		void setParDeRegistros(ParDeRegistros registro, word dato);
		void setBandera(Bandera bandera, bool dato);

		// Accesores
		Memoria& getMemoria();	
		byte getRegistro(Registro registro) const;
		word getParDeRegistros(ParDeRegistros registro) const;
		bool getBandera(Bandera bandera) const;


	private:
		typedef void (Microprocesador::*Func_ptr)(const Instruccion&);

		Memoria &memoria_;
		byte registro_[cantidad_registros];
		word sp_, pc_;
		bool halt_;
		Func_ptr instruccion_[cantidad_tipos_de_instruccion];
		Decodificador decodificador_;
	private:
		void mov(const Instruccion &instruccion);
		void mvi(const Instruccion &instruccion);
		void lxi(const Instruccion &instruccion);
		void lda(const Instruccion &instruccion);
		void sta(const Instruccion &instruccion);
		void lhld(const Instruccion &instruccion);
		void shld(const Instruccion &instruccion);
		void ldax(const Instruccion &instruccion);
		void stax(const Instruccion &instruccion);
		void xchg(const Instruccion &instruccion);

		void add(const Instruccion &instruccion);
		void adi(const Instruccion &instruccion);
		void adc(const Instruccion &instruccion);
		void aci(const Instruccion &instruccion);
		void sub(const Instruccion &instruccion);
		void sui(const Instruccion &instruccion);
		void sbb(const Instruccion &instruccion);
		void sbi(const Instruccion &instruccion);
		void inr(const Instruccion &instruccion);
		void dcr(const Instruccion &instruccion);
		void inx(const Instruccion &instruccion);
		void dcx(const Instruccion &instruccion);
		void dad(const Instruccion &instruccion);
		void daa(const Instruccion &instruccion);

		void ana(const Instruccion &instruccion);
		void ani(const Instruccion &instruccion);
		void xra(const Instruccion &instruccion);
		void xri(const Instruccion &instruccion);
		void ora(const Instruccion &instruccion);
		void ori(const Instruccion &instruccion);
		void cmp(const Instruccion &instruccion);
		void cpi(const Instruccion &instruccion);
		void rlc(const Instruccion &instruccion);
		void rrc(const Instruccion &instruccion);
		void ral(const Instruccion &instruccion);
		void rar(const Instruccion &instruccion);
		void cma(const Instruccion &instruccion);
		void cmc(const Instruccion &instruccion);
		void stc(const Instruccion &instruccion);

		void jmp(const Instruccion &instruccion);
		void jcond(const Instruccion &instruccion);
		void call(const Instruccion &instruccion);
		void ccond(const Instruccion &instruccion);
		void ret(const Instruccion &instruccion);
		void rcond(const Instruccion &instruccion);
		void rst(const Instruccion &instruccion);
		void pchl(const Instruccion &instruccion);

		void push(const Instruccion &instruccion);
		void pop(const Instruccion &instruccion);
		void xthl(const Instruccion &instruccion);
		void sphl(const Instruccion &instruccion);
		void in(const Instruccion &instruccion);
		void out(const Instruccion &instruccion);
		void ei(const Instruccion &instruccion);
		void di(const Instruccion &instruccion);
		void hlt(const Instruccion &instruccion);
		void nop(const Instruccion &instruccion);
		void rim(const Instruccion &instruccion);
		void sim(const Instruccion &instruccion);

};
#endif
